using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel;
using System.Configuration;
using Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel.Mappings.Enums;
using Microsoft.Practices.RepositoryFactory.CustomPages.CreateRepositoryPages;
using Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel.Mappings;
using Microsoft.Practices.RepositoryFactory.Properties;
using System.Globalization;
using Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel.NamingConventions;

namespace Microsoft.Practices.RepositoryFactory.CustomPages
{
   public partial class CreateMappingWizard : Form
   {
      private Entity entity;
      private ConnectionStringSettings connectionSettings;
      private OperationType operationType;
      private UserControl currentPage;
      private EntityStoredProcedureMapping currentMapping;
      private bool editMode;

      public CreateMappingWizard(Entity entity, ConnectionStringSettings connectionSettings,
          OperationType operationType)
      {
         InitializeComponent();

         this.entity = entity;
         this.connectionSettings = connectionSettings;
         this.operationType = operationType;
         this.currentMapping = new EntityStoredProcedureMapping(null, false, null, operationType);

         ConfigureLayout(false);
      }

      public CreateMappingWizard(Entity entity, ConnectionStringSettings connectionSettings,
          OperationType operationType, EntityStoredProcedureMapping existingMapping)
      {
         InitializeComponent();

         this.entity = entity;
         this.connectionSettings = connectionSettings;
         this.operationType = operationType;
         this.currentMapping = existingMapping;

         ConfigureLayout(true);

         editMode = true;
      }

      private void ConfigureLayout(bool editMode)
      {
         pageContainerGroup.Text = "Operation wizard";
         CreateFirstPage();
         if (operationType == OperationType.DeleteOne)
         {
            nextButton.Text = "Finish";
         }
         DisplaySummaryMessage();
      }

      private void DisplaySummaryMessage()
      {
         string operationType = currentMapping.OperationType.ToString();
         string operationName = currentMapping.OperationName;
         string returnType = OperationType.DeleteOne.ToString();
         string parameters = OperationType.DeleteOne.ToString();
         string storedProcedureName = currentMapping.Procedure;


         switch (currentMapping.OperationType)
         {
            case OperationType.InsertOne:
            // do nothing
            case OperationType.InsertMany:
            // do nothing
            case OperationType.UpdateOne:
               returnType = "void";
               parameters = string.Format("{0} entity", entity.Name);
               break;
            case OperationType.UpdateMany:
               returnType = "void";
               parameters = string.Format("{0} entity", entity.Name);
               break;
            case OperationType.DeleteOne:
               returnType = "void";
               parameters = GetIdentityParameters(currentMapping.Identity, false);
               break;
            case OperationType.DeleteMany:
               returnType = "void";
               parameters = GetIdentityParameters(currentMapping.Identity, false);
               break;
            case OperationType.GetOne:
               returnType = entity.Name;
               parameters = GetIdentityParameters(currentMapping.Identity, false);
               break;
            case OperationType.GetOneComplex:
               returnType = entity.Name;
               parameters = GetIdentityParameters(currentMapping.Identity, false);
               break;
            case OperationType.GetAll:
               returnType = string.Format(CultureInfo.InvariantCulture, "List<{0}>", entity.Name);
               parameters = string.Empty;
               break;
            case OperationType.GetMany:
               returnType = string.Format(CultureInfo.InvariantCulture, "List<{0}>", entity.Name);
               parameters = GetIdentityParameters(currentMapping.Identity, false);
               break;
         }


         string message = string.Format(Resources.SummaryMessage, operationType, operationName, returnType,
             entity.Name, operationName, parameters, storedProcedureName);
         summaryMessageTextbox.Text = message;
      }

      private void CreateFirstPage()
      {
         CreateOperationViewPresenter presenter = new CreateOperationViewPresenter(entity, currentMapping, connectionSettings);
         CreateOperationPage page = new CreateOperationPage(presenter);
         pageContainerPanel.Controls.Clear();
         pageContainerPanel.Controls.Add(page);
         currentPage = page;
         previousButton.Enabled = false;
      }

      private void nextButton_Click(object sender, EventArgs e)
      {
         if (((IWizardPage)currentPage).IsDataValid)
         {
            ((IWizardPage)currentPage).Complete();

            switch (this.operationType)
            {
               case OperationType.GetOne:
               case OperationType.GetOneComplex:
               case OperationType.GetAll:
               case OperationType.GetMany:
                  NavigateNextWhenGetOperation();
                  break;
               case OperationType.InsertOne:
               case OperationType.InsertMany:
               case OperationType.UpdateOne:
                  NavigateNextWhenUpdateOperation();
                  break;
               case OperationType.UpdateMany:
                  NavigateNextWhenUpdateOperation();
                  break;
               case OperationType.DeleteOne:
                  NavigateNextWhenDeleteOperation();
                  break;
               case OperationType.DeleteMany:
                  NavigateNextWhenDeleteOperation();
                  break;
            }
         }
         DisplaySummaryMessage();
      }

      private void NavigateNextWhenGetOperation()
      {
         pageContainerPanel.Controls.Clear();
         UserControl page = null;

         if (currentPage is CreateOperationPage)
         {
            MapResultSetPagePresenter presenter = new MapResultSetPagePresenter(entity,
                           currentMapping,
                           connectionSettings);
            page = new MapResultSetPage(presenter);
            previousButton.Enabled = true;
            nextButton.Text = "Finish";
         }
         else if (currentPage is MapResultSetPage)
         {
            CompleteWizard();
            return;
         }

         currentPage = page;
         pageContainerPanel.Controls.Add(page);
      }

      private void CompleteWizard()
      {
         if (!editMode)
         {
            this.entity.StoredProcedureMappings.Add(currentMapping);
         }
         this.DialogResult = DialogResult.OK;
         this.Close();
      }

      private void NavigateNextWhenUpdateOperation()
      {
         pageContainerPanel.Controls.Clear();
         UserControl page = null;

         if (currentPage is CreateOperationPage)
         {
            MapInputParametersPagePresenter presenter = new MapInputParametersPagePresenter(entity,
                           currentMapping,
                           connectionSettings);
            page = new MapInputParametersPage(presenter);
            previousButton.Enabled = true;
            nextButton.Text = "Finish";
         }
         else if (currentPage is MapInputParametersPage)
         {
            CompleteWizard();
            return;
         }

         currentPage = page;
         pageContainerPanel.Controls.Add(page);
      }

      private void NavigateNextWhenDeleteOperation()
      {
         pageContainerPanel.Controls.Clear();
         UserControl page = null;

         if (currentPage is CreateOperationPage)
         {
            CompleteWizard();
            return;
         }

         currentPage = page;
         pageContainerPanel.Controls.Add(page);
      }

      private void previousButton_Click(object sender, EventArgs e)
      {
         switch (this.operationType)
         {
            case OperationType.DeleteOne:
            case OperationType.DeleteMany:
            case OperationType.GetOne:
            case OperationType.GetOneComplex:
            case OperationType.GetAll:
            case OperationType.GetMany:
               NavigateBackWhenGetOperation();
               break;
            case OperationType.InsertOne:
            case OperationType.InsertMany:
            case OperationType.UpdateOne:
               NavigateBackWhenUpdateOperation();
               break;
            case OperationType.UpdateMany:
               NavigateBackWhenUpdateOperation();
               break;
         }
         DisplaySummaryMessage();
      }

      private void NavigateBackWhenGetOperation()
      {
         pageContainerPanel.Controls.Clear();
         UserControl page = null;

         if (currentPage is MapResultSetPage)
         {
            CreateOperationViewPresenter presenter = new CreateOperationViewPresenter(entity, currentMapping,
                connectionSettings);

            page = new CreateOperationPage(presenter);
            previousButton.Enabled = false;
            nextButton.Text = "Next >>";
         }

         currentPage = page;
         pageContainerPanel.Controls.Add(page);
      }

      private void NavigateBackWhenUpdateOperation()
      {
         pageContainerPanel.Controls.Clear();
         UserControl page = null;

         if (currentPage is MapInputParametersPage)
         {
            CreateOperationViewPresenter presenter = new CreateOperationViewPresenter(entity, currentMapping,
                connectionSettings);

            page = new CreateOperationPage(presenter);
            previousButton.Enabled = false;
            nextButton.Text = "Next >>";
         }

         currentPage = page;
         pageContainerPanel.Controls.Add(page);
      }

      private void cancelButton_Click(object sender, EventArgs e)
      {
         this.DialogResult = DialogResult.Cancel;
         this.Close();
      }

      private string GetIdentityParameters(Identity identity, bool variablesNamesOnly)
      {
         string response = "";

         if (identity != null)
         {
            foreach (PropertyParameterMapping parameterMapping in identity.ParameterMappings)
            {
               if (variablesNamesOnly)
               {
                  response += NamingHelper.GetVariableName(parameterMapping.Property) + ", ";
               }
               else
               {
                  string propertyType = parameterMapping.ParameterInstance.DbDataType.Type.ToString();
                  response += propertyType + " " + NamingHelper.GetVariableName(parameterMapping.Property) + ", ";
               }
            }

            if (response.Length > 0)
            {
               response = response.Substring(0, response.Length - 2);
            }
         }

         return response;
      }
   }
}